# encoding=utf-8
from pprint import pprint

import jsonpath
from configs.logging_settings import LogStateString
from utils.logger_utils import savelog
from configs.commom import notice_style_zhaobiao, replaceinfo_dict_zhaobiao, replaceinfo_dict_zhongbiao, \
    notice_style_zhongbiao

from spidertools.utils.text_utils import clean_html_whitesplace

json_path_base = '$..%s'
check_keys_dict = {
    "招标公告": ["项目名称", "标段名称"],
    "中标公告": ["项目名称", "标段名称", "中标信息名称"]
}

warning_keys = {
    "招标公告":["工程地址"],
    "中标公告":[],
}

def check_warning_key_exist(json_obj, result):
    announcement_type = json_obj["工程公告信息"]['公告类型']
    for check_key in warning_keys[announcement_type]:
        path = json_path_base % check_key
        check_value = jsonpath.jsonpath(json_obj, path)
        if check_value == False:
            add_checkresult_to_dict(LogStateString.Warning_LockKeyWords, check_key, [], result)
        else:
            check_value = [v for v in check_value if v != ""]
            if not check_value:
                add_checkresult_to_dict(LogStateString.Warning_LockKeyWords, check_key, [], result)

def check_key_exist(json_obj, result):
    announcement_type = json_obj["工程公告信息"]['公告类型']
    for check_key in check_keys_dict[announcement_type]:
        path = json_path_base % check_key
        check_value = jsonpath.jsonpath(json_obj, path)
        if check_value == False:
            add_checkresult_to_dict(LogStateString.FatalError_LockKeyWords, check_key, [], result)
        else:
            check_value = [v for v in check_value if v != ""]
            if not check_value:
                add_checkresult_to_dict(LogStateString.FatalError_LockKeyWords, check_key, [], result)




def add_checkresult_to_dict(log_code, check_key, check_value, result):
    if log_code:
        if log_code not in result:
            result[log_code] = {}
        if check_key not in result[log_code]:
            result[log_code][check_key] = []

        if check_value:
            if type(check_value) == list:
                result[log_code][check_key].extend(check_value)
            elif type(check_value) == str:
                result[log_code][check_key].append(check_value)
            elif type(check_value) == dict:
                join_str = "$$$$".join(["%s:%s" % (key, value) for key, value in check_value.items()])
                result[log_code][check_key].append(join_str)


def traversal_json(json_obj, check_funcs, result):
    '''
    遍历整个json
    :param json_obj:
    :return:
    '''

    for key, value in list(json_obj.items()):
        if type(value) == dict:
            traversal_json(json_obj[key], check_funcs, result)
        elif type(value) == list and value and type(value[0]) == dict:
            for v in value:
                traversal_json(v, check_funcs, result)

        for func in check_funcs['common']:
            logcode, log_value = func(value, key)
            add_checkresult_to_dict(logcode, key, log_value, result)

        if key in check_funcs:
            for func in check_funcs[key]:
                # 将错误写到result里面去
                logcode, log_value = func(value)
                add_checkresult_to_dict(logcode, key, log_value, result)
        if type(value) == list and value and type(value[0]) == str: #################################1.28修改
            value = [v.strip() for v in value if v.strip()]
            json_obj[key] = value
            if not value:
                del json_obj[key]
        elif not value:
            del json_obj[key]#########

def check_len(text_or_list):
    '''
    判断文本长度是不是大于100
    '''
    log_code = ""
    tolong_list = []
    if type(text_or_list) == str:
        text_or_list = clean_html_whitesplace(text_or_list)
        if len(text_or_list) > 100:
            log_code = LogStateString.Waring_ContentLenMoreThan100
            tolong_list.append(text_or_list)
    elif type(text_or_list) == list:
        for v in text_or_list:
            v = clean_html_whitesplace(v)
            if len(v) > 100:
                log_code = LogStateString.Waring_ContentLenMoreThan100
                tolong_list.append(v)

    return log_code, tolong_list


def common_check_colon(obj, check_key):
    log_code = ""
    log_str = []
    if isinstance(obj, str):
        log_code, log_str = check_colon(obj)
    return log_code, log_str

def check_colon(text_or_list):
    log_code = ""
    colon_list = []
    if type(text_or_list) == str:
        text_or_list = clean_html_whitesplace(text_or_list)
        if ":" in text_or_list or "：" in text_or_list:
            log_code = LogStateString.Waring_ContainsColon
            colon_list.append(text_or_list)
    elif type(text_or_list) == list:
        for v in text_or_list:
            v = clean_html_whitesplace(v)
            if ":" in text_or_list or "：" in text_or_list:
                log_code = LogStateString.Waring_ContainsColon
                colon_list.append(v)

    return log_code, colon_list



def check_value_type_equal_list(obj):
    '''
    判断类型是不是list类型。这个方法只要是确保联系人相关的信息存储的结构都是list类型
    '''
    log_code = ""
    if type(obj) != list:
        log_code = LogStateString.FatalError_TypeNotList
    return log_code, []


# no need check len
more_than_len_100_true = ["工程规模", "招标内容", "招标范围", "项目简介", "工程规模", "标段范围", "标段投标人资质类别要求", "公告标题"]


def check_WeiZhiKeyWords(obj):
    '''检查最后的json里面是不是有未知内容'''
    log_code = ""
    if obj:
        log_code = LogStateString.Waring_WeiZhiKeyWords
    return log_code, obj


def common_check_len(obj, check_key):
    log_code = ""
    log_str = []
    if check_key not in more_than_len_100_true and isinstance(obj, str):
        log_code, log_str = check_len(obj)
    return log_code, log_str


def check_has_tokens(token_list,check_str):
    found = False
    for token in token_list:
        if token in check_str:
            found = True
            break
    return found

def company_check(obj):
    '''判断一个str是不是一个合法的企业
        第一期：简单点，一个合理的公司名称里面应包含 公司 两个字
    '''
    log_code = ""
    valid_company_tokens = ["公司",'政府',"运输局",'发展中心','交通局','建设中心','管理处','指挥部','监督站','重点办','办事处','公路处',"委员会",'农业农村局',"水利局"]
    if type(obj) == list:
        for v in obj:
            if not check_has_tokens(valid_company_tokens,v):
                log_code = LogStateString.Warning_NotValidCompanyName
                break
    elif type(obj) == str:
        if not check_has_tokens(valid_company_tokens,obj):
            log_code = LogStateString.Warning_NotValidCompanyName
    return log_code,obj


def address_check(obj):
    '''地址检查
    1.如果地址长度小于6,则报 Warning_TooShortAddress
    '''
    log_code = ""
    if type(obj) == list :
        for v in obj:
            if len(v) < 6:
                log_code = LogStateString.Warning_TooShortAddress
            break
    elif type(obj) == str:
        if len(obj) < 6:
            log_code = LogStateString.Warning_TooShortAddress


    return log_code,obj




check_function = {
    "common": [common_check_len,common_check_colon],
    "未知": [check_WeiZhiKeyWords,],


    # 工程投标信息
    "中标信息名称":[company_check,],
    "中标候选人名称":[company_check,],
    '中标信息地址':[address_check,],



    # 工程招标信息
    "招标人信息名称": [check_value_type_equal_list,company_check ],
    "招标人信息地址": [address_check,],
    "招标代理机构名称": [check_value_type_equal_list,company_check ],
    "招标代理机构地址": [address_check],

    # 工程基本信息
    "工程地址":[address_check],




}


def check_json(json_obj):
    result = {}
    traversal_json(json_obj, check_function, result)
    check_key_exist(json_obj, result)
    check_warning_key_exist(json_obj,result)
    return result


def save_check_result_to_file(check_result, parsed_result, mongo_data):
    if check_result:
        data = {}
        data["original_data"] = mongo_data
        data["extract_data"] = parsed_result
        for log_code, log_key_values in check_result.items():
            save_str = ""
            for key, values in log_key_values.items():
                save_str += "#%s:%s" % (key, "$$$$".join(values))
            savelog(log_code, save_str, msg_dict=data)


def changedict(result, replaceinfo_dict):
    weizhidict = result['未知']
    change_first_field = replaceinfo_dict.keys()
    for first_field in change_first_field:
        for changek_second, changev_second in replaceinfo_dict[first_field].items():
            if changek_second in weizhidict.keys():
                if first_field not in result.keys():
                    result[first_field] = {}
                    result[first_field][changev_second] = weizhidict[changek_second]
                    del weizhidict[changek_second]
                else:
                    if isinstance(result[first_field], list):
                        exist_flag, index_num = 0, 0
                        for index_, dict_v in enumerate(result[first_field]):
                            if changev_second in dict_v:
                                exist_flag = 1
                                index_num = index_
                                break
                        if not exist_flag:
                            result[first_field][index_num][changev_second] = weizhidict[changek_second]
                            del weizhidict[changek_second]
                    else:  # dict
                        if changev_second not in result[first_field].keys():
                            result[first_field][changev_second] = {}
                            result[first_field][changev_second] = weizhidict[changek_second]
                            del weizhidict[changek_second]
    if not weizhidict:
        del result['未知']
    return result


def translatedict(result):
    ''' 将未知里面的key根据notice_style转换'''

    check_weizhi_exists(result)
    update_toubiao_dict(result)

    if result["工程公告信息"]['公告类型'] in notice_style_zhaobiao:
        result = changedict(result, replaceinfo_dict_zhaobiao)
        return result
    elif result["工程公告信息"]['公告类型'] in notice_style_zhongbiao:
        result = changedict(result, replaceinfo_dict_zhongbiao)
        return result
    else:
        return result


def check_weizhi_exists(result):
    '''
    判断未知里面的内容是不是在之前的key里面已经出现
    出现了，就可以删除
    '''

    if '未知' in result:
        # if result['工程公告信息']['公告类型'] == '招标公告':
        ## 目前只处理了招标人和招标代理机构相关的
        for key, value in list(result["未知"].items()):
            if type(value) == list:
                for parse_mode in ["招标人信息", "招标代理机构"]:
                    real_key = parse_mode + key.replace("未知", "")
                    search_jsonpath = json_path_base % real_key
                    search_result = jsonpath.jsonpath(result, search_jsonpath)
                    if search_result:
                        # 一个key值应该只能查找到一个值
                        value = list(set(value) - set(search_result[0]))
                if not value:
                    del result["未知"][key]
                else:
                    result['未知'][key] = value
        if result['工程公告信息']['公告类型'] == '中标公告':
            for key, value in list(result["未知"].items()):
                if type(value) == list:
                    real_key = "中标信息" + key.replace("未知", "")
                    search_jsonpath = json_path_base % real_key
                    search_result = jsonpath.jsonpath(result, search_jsonpath)
                    if search_result:
                        # 一个key值应该只能查找到一个值
                        if not isinstance(type(value), type(search_result[0])) and type(value) == list:
                            value = value[0]  # 目前只遇到一个的情况，后续有其他情形再修改
                        value = list(set(value) - set(search_result[0]))
                    if not value:
                        del result["未知"][key]
        for key, value in list(result["未知"].items()):
            if type(value) == str:  ############################sun
                Found = False
                for parse_mode in ["工程基本信息工期", '标段工期','中标信息工期']:
                    real_key = parse_mode
                    search_jsonpath = json_path_base % real_key
                    search_result = jsonpath.jsonpath(result, search_jsonpath)
                    if search_result:
                        Found = True
                        break
                if Found:
                    del result["未知"][key]

def update_toubiao_dict(result):
    '''
    更新投标信息里面的中标内容，
    如果不存在中标信息名称，但是存在中标候选人名称，可以吧第一个中标候选人当做中标人
    '''
    if '工程投标信息' in result:
        winner_json_path = json_path_base % '中标信息名称'
        check_winner = jsonpath.jsonpath(result, winner_json_path)
        if not check_winner:
            for item in result["工程投标信息"]:
                if '中标候选人名称' in item:
                    item["中标信息名称"] = item['中标候选人名称']
                    break
        elif len(check_winner) >= 1:
            # 有多个中标人
            find_first = False
            for item in result["工程投标信息"]:
                if "中标信息名称" in item:
                    if not find_first:
                        find_first = True
                    else:
                        item["中标候选人名称"] = item['中标信息名称']
                        del item['中标信息名称']





if __name__ == '__main__':

    obj = {
        "工程基本信息": {
            "项目名称": "344省道邳州段建设工程施工项目",
            "工程地址": "江苏省邳州市",
            "工程开工时间": "2017-11-08",
            "工程竣工时间": "2019-12-28",
            "项目编号": "XZJT20170704140",
            "工程类别": "施工",
            "工程所属省份": "江苏",
            "工程所属市": "徐州市"
        },
        "工程招标信息": {
            "招标内容": "招标内容 本工程为344省道邳州段建设工程施工项目,本次招标划分为2个施工标段,标段划分如下 第一标段 京杭运河钢桁拱特大桥工程(主跨120米。桩号K2+776.88~K4+992.72,长2215.84米。)徐洪河大桥主桥工程(变截面钢腹板混凝土连续箱梁,主跨100米,长764.28米,桩号K16+047.10--K15+282.82)、白马河大桥(预应力组合箱梁,长104.52米,桩号K39+235.24--K39+339.76)。第二标段 路基路面工程(全线除第一标段以外的所有路基、路面、桥梁、涵洞等工程及附属工程)。",
            "投标截止时间": "2017-10-10 09:30",
            "招标人信息名称": [
                "邳州市交通运输局"
            ],
            "招标人信息地址": [
                "邳州市建设南路45号"
            ],
            "招标代理机构名称": [
                "中招国际招标有限公司"
            ],
            "招标代理机构地址": [
                "南京市秦淮区军农路3号2栋2楼"
            ],
            "招标人信息联系人": [
                "基业欣"
            ],
            "招标人信息电话": [
                "18551711233"
            ],
            "招标人信息传真": [
                "025-83750998"
            ]
        },
        "工程公告信息": {
            "公告标题": "344省道邳州段建设工程施工项目（重新公告）",
            "工程公告信息发布时间": "2017-09-11",
            "公告类型": "招标公告"
        }
    }

    pprint(check_json(obj))